package com.wfc.libnetwork;

import android.graphics.text.LineBreaker;
import android.util.Log;

import androidx.annotation.IntDef;

import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.Response;

//两个泛型参数：第一个泛型为Response返回实体  第二个泛型参数为 请求的子类
public abstract class Request<T,R> {

    private static final String TAG = "Request";
    protected String mUrl;
    protected HashMap<String,String> headers=new HashMap<>(); //header
    protected HashMap<String,Object> params=new HashMap<>();  //请求参数

    //仅仅只访问本地缓存
    public static final int CACHE_ONLY=1;
    //先访问缓存，同时发起网络的请求，成功后缓存到本地
    public static final int CACHE_FIRST=2;
    //仅仅只访问服务器，不存任何缓存
    public static final int NET_ONLY=3;
    //先访问网络，成功后缓存到本地
    public static final int NET_CACHE=4;
    private String cacheKey;

    private Type mType;
    private Class mClaz;

    //注解标注下请求类型:使用 @interface 自定义注解时，自动继承了java.lang.annotation.Annotation接口，
    @IntDef({CACHE_ONLY,CACHE_FIRST,NET_ONLY,NET_CACHE})
    public @interface CacheStrategy{

    }



    public Request(String mUrl) {

    }

    public  R addHeader(String key,String value){
        headers.put(key,value);
        return (R)this;
    }


    public  R addHeader(String key,Object value){
        //value 只运行8中基本类型
        try {
            Field field= value.getClass().getField("TYPE");
            Class claz = null;
            try {
                claz = (Class) field.get(null);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            if(claz.isPrimitive()){ //如果是基本数据类型
            params.put(key,value);
         }

        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        }
        return (R)this;
    }

    //设置了缓存的类型，那么就需要有一个缓存的key
    public R cacheKey(String key){
        this.cacheKey=key;
        return (R)this;
    }

    public R responseType(Type type){
        mType=type;
        return (R)this;

    }
    public R responseType(Class claz){
        mClaz=claz;
        return (R)this;

    }

    //网络请求的真正方法
    public void execute(JsonCallback<T> callback){
          //执行异步方法
          getCall().enqueue(new Callback() {
              @Override
              public void onFailure(@NotNull Call call, @NotNull IOException e) {
                  ApiResponse<T> reponse=new ApiResponse<>();
                  reponse.message=e.getMessage();
                  callback.onError(reponse);

              }

              @Override
              public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
                  ApiResponse<T> reponse=parseResponse(response,callback);


              }
          });

    }

    //针对异步请求，携带了CallBack
    private ApiResponse<T> parseResponse(Response response,JsonCallback<T> callback) {
        String message=null;
        int status=response.code();
        boolean success=response.isSuccessful();
        ApiResponse<T> result=new ApiResponse<>();
         Convert convert=ApiService.sConvert;
        try{
            String content=response.body().string();
            if(success){
                if(callback!=null){
                    ParameterizedType type= (ParameterizedType) callback.getClass().getGenericSuperclass();
                    Type argument=type.getActualTypeArguments()[0];
                   result.body= (T) convert.convert(content,argument);
                }else if(mType!=null){
                    result.body= (T) convert.convert(content,mType);
                }else if(mClaz!=null){
                    result.body= (T) convert.convert(content,mClaz);
                }else {
                    Log.e(TAG," parseRespone 无法解析");
                }
            }else {
                message=content;
            }
        }catch (Exception e){
            message=e.getMessage();
            success=false;
           // e.printStackTrace();
        }
        result.success=success;
        result.status=status;
        result.message=message;

        return result;
    }

    private Call getCall() {
        okhttp3.Request.Builder builder=new okhttp3.Request.Builder();
        addHeader(builder);
        okhttp3.Request request=geterateRequest(builder);
        Call call=ApiService.okHttpClient.newCall(request);
        return call;

    }

    protected abstract okhttp3.Request geterateRequest(okhttp3.Request.Builder builder);

    //把header 添加到builder 里面去
    private void addHeader(okhttp3.Request.Builder builder) {
         for(Map.Entry<String,String>  entry : headers.entrySet()){
             builder.addHeader(entry.getKey(),entry.getValue());
        }
    }

    public ApiResponse<T> execute(){

        try {
            Response response=getCall().execute();
            ApiResponse<T> result=parseResponse(response,null);
            return result;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

}
